package com.hpsk.utils;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import com.googlecode.aviator.Options;
import com.hpsk.aviator.function.AvgFunction;
import com.hpsk.aviator.module.DateTimeModule;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Slf4j
public class AviatorEvaluatorUtil {

    private static final AviatorEvaluatorInstance aviatorEvaluator = AviatorEvaluator.newInstance();
    private static final String REQUIRED = "let dateTime = require('dateTime'); ";
    private static final Boolean CACHED = true;
    static {
        //样例自定义函数
        aviatorEvaluator.addFunction(new AvgFunction());
        aviatorEvaluator.setOption(Options.CAPTURE_FUNCTION_ARGS, true);
        aviatorEvaluator.setOption(Options.MAX_LOOP_COUNT, 50000);
        aviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
        aviatorEvaluator.setOption(Options.ALWAYS_PARSE_INTEGRAL_NUMBER_INTO_DECIMAL, true);
        aviatorEvaluator.setCachedExpressionByDefault(true);
        aviatorEvaluator.useLRUExpressionCache(10000);
        // add modules
        try {
            //需配合let dateTime = require('dateTime')
            aviatorEvaluator.addModule(DateTimeModule.class);
        } catch (NoSuchMethodException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static Boolean verify(String expression, Map<String, Object> params){
        return ObjectUtil.isNotEmpty(expression) && (boolean) calculate(expression, params);
    }

    public static Object calculate(String expression, Map<String, Object> params){
        expression = REQUIRED.concat(expression);
        Object execute = null;
        try{
            execute = aviatorEvaluator.compile(expression, CACHED).execute(params);
        }catch (Exception e){
            if (e.getMessage().contains("Could not find variable")) {
                log.warn("表达式计算异常：{}", e.getMessage().replace("Could not find variable", "表达式中不存在变量:"));
            } else {
                log.error("表达式计算异常", e);
            }
        }
        return execute;
    }

    /**
     * 校验表达式计算
     *
     * @param expression 表达式
     * @param params     需要替换的表达式参数
     * @return calculate result
     */
    public static Boolean validate(String expression, Map<String, Object> params) {
        expression = REQUIRED.concat(expression);
        Map<String, Object> map = MapUtil.newHashMap();
        if(params != null){
            for (String key : params.keySet()) {
                map.put(key, params.get(key));
            }
        }
        Boolean result;
        try {
            aviatorEvaluator.compile(expression, CACHED).execute(map);
        } catch (Exception e) {
            log.error("表达式：{}", expression);
            if (e.getMessage() != null && e.getMessage().contains("Could not find variable")) {
                log.warn("表达式计算异常：{}", e.getMessage().replace("Could not find variable", "表达式中不存在变量:"));
//                return Boolean.FALSE;
            } else {
                log.error("表达式计算异常", e);
            }
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    public static void main(String[] args) {
        String expression = "dateTime.format(111'yyyy-MM-dd') == '2025-04-12'";
//        Map<String, Object> params = MapUtil.of("a", "yyyy-MM-dd");

        String a = "average(a,b,c)";
                Map<String, Object> params = MapUtil.of("a", 10);
        params.put("b", 20);
        params.put("c", 20);
        if(AviatorEvaluatorUtil.validate(expression, null)){
            Boolean verify = AviatorEvaluatorUtil.verify(expression, null);
            System.out.println(verify);
        }
//        System.out.println(calculate1);
        Object calculate = AviatorEvaluatorUtil.calculate(a, params);
        log.info("表达式计算结果:{}", calculate);
//        log.info("表达式计算结果:{}", AviatorEvaluatorUtil.verify(expression, params));
    }

}
